home *** CD-ROM | disk | FTP | other *** search
/ Sun Solutions 1997 April to September / Sun Solutions CD - APR '97 - SEP '97 (704-3778-12 Rev. H)(Sun Microsystems, Inc.)(1997).iso / products / Hyperion / src / setup.c < prev    next >
C/C++ Source or Header  |  1997-02-26  |  33KB  |  1,108 lines

  1. #include <xview/xview.h>
  2. #include <xview/font.h>
  3. #include <xview/panel.h>
  4. #include <xview/svrimage.h>
  5. #include "workman_ui.h"
  6.  
  7. static char *ident = "@(#)setup.c    1.26 5/21/94";
  8.  
  9. /*
  10.  * Define a few macros to make relative positioning easier.
  11.  */
  12. #define top(item) ((int) xv_get(item, XV_Y))
  13. #define hei(item) ((int) xv_get(item, XV_HEIGHT))
  14. #define bot(item) (top(item) + hei(item))
  15. #define lef(item) ((int) xv_get(item, XV_X))
  16. #define wid(item) ((int) xv_get(item, XV_WIDTH))
  17. #define rig(item) (lef(item) + wid(item))
  18.  
  19. #define put_down(t, s, off) xv_set(t, XV_Y, bot(s) + off, NULL)
  20. #define put_right(t, s, off) xv_set(t, XV_X, rig(s) + off, NULL)
  21. #define center_x(t, s) xv_set(t, XV_X, (lef(s) + rig(s) - wid(t)) / 2, NULL)
  22. #define center_y(t, s) xv_set(t, XV_Y, (top(s) + bot(s) - hei(t)) / 2, NULL)
  23.  
  24. extern void change_track(),
  25.     window1_button2_notify_callback(),
  26.     window1_button3_notify_callback(),
  27.     window1_button4_notify_callback(),
  28.     popup1_buttonpl_notify_callback(),
  29.     popup1_button1_notify_callback(),
  30.     goodies_playnewcds_notify_callback(),
  31.     goodies_abrepeat_notify_callback(),
  32.     plpopup_button7_notify_callback(),
  33.     change_mode(), delete_from_playlist(), playlist_notify(),
  34.     delete_playlist(), rename_playlist(), switch_playlists(),
  35.     slide_balance(), section_start(), section_end(), change_pos(),
  36.     next_stopmode(), set_volume(), next_playmode_default(),
  37.     update_title(), update_trackname(), name_entered(),
  38.     set_which_volume(), set_default_volume(), save_config(),
  39.     cdinfo_reset(), split_track(), delete_track(), index_scan();
  40.  
  41. int    basic_spacing = 0;
  42. int    small_buttons = -1;
  43. int    big_spaces = 0;        /* Flag: spaces are as big as digits */
  44.  
  45. static unsigned short bits[] = {
  46. #include "bitmaps/icon"
  47. };
  48.  
  49. /* Make the window a particular size initially so we can position it. */
  50. #define Dft_Size 50
  51.  
  52. /*
  53.  * Create the main window and its contents.
  54.  */
  55. window1_objects *
  56. window1_objects_init(ip, owner)
  57.     window1_objects    *ip;
  58.     Xv_opaque        owner;
  59. {
  60.     Xv_opaque    image, image_mask, speaker_image, mode_image0,
  61.             mode_image1, mode_image2, mode_image3, mode_image4,
  62.             mode_image5;
  63.     Display        *dpy;
  64.     Xv_Screen    screen;
  65.     Panel_item    item;
  66.     int        space, screen_no, swidth, sheight, x;
  67.     static unsigned short mask_bits[] = {
  68. #include "bitmaps/iconmask"
  69.     }, speaker_bits[] = {
  70. #include "bitmaps/loud.icon"
  71.     }, mode_bits0[] = {
  72. #include "bitmaps/rew.button"
  73.     }, mode_bits1[] = {
  74. #include "bitmaps/play.button"
  75.     }, mode_bits2[] = {
  76. #include "bitmaps/ff.button"
  77.     }, mode_bits3[] = {
  78. #include "bitmaps/pause.button"
  79.     }, mode_bits4[] = {
  80. #include "bitmaps/stop.button"
  81.     }, mode_bits5[] = {
  82. #include "bitmaps/eject.button"
  83.     }, small_bits0[] = {
  84. #include "bitmaps/rew.button.small"
  85.     }, small_bits1[] = {
  86. #include "bitmaps/play.button.small"
  87.     }, small_bits2[] = {
  88. #include "bitmaps/ff.button.small"
  89.     }, small_bits3[] = {
  90. #include "bitmaps/pause.button.small"
  91.     }, small_bits4[] = {
  92. #include "bitmaps/stop.button.small"
  93.     }, small_bits5[] = {
  94. #include "bitmaps/eject.button.small"
  95.     };
  96.  
  97.     if ((ip = (window1_objects *) calloc(1,
  98.                 sizeof(window1_objects))) == NULL)
  99.         return (NULL);
  100.  
  101.     image = xv_create(XV_NULL, SERVER_IMAGE, SERVER_IMAGE_DEPTH, 1,
  102.         SERVER_IMAGE_BITS, bits, XV_WIDTH, 64, XV_HEIGHT, 64,
  103.         NULL);
  104.     image_mask = xv_create(XV_NULL, SERVER_IMAGE, SERVER_IMAGE_DEPTH,
  105.         1, SERVER_IMAGE_BITS, mask_bits, XV_WIDTH, 64,
  106.         XV_HEIGHT, 64, NULL);
  107.     ip->window1 = xv_create(owner, FRAME, XV_KEY_DATA, INSTANCE,
  108.         ip, XV_LABEL, "WorkMan", FRAME_SHOW_FOOTER, FALSE,
  109.         FRAME_SHOW_RESIZE_CORNER, FALSE, FRAME_ICON,
  110.         xv_create(XV_NULL, ICON, ICON_IMAGE, image,
  111.         ICON_MASK_IMAGE, image_mask, XV_LABEL, "Wait...",
  112.         NULL), XV_WIDTH, Dft_Size, XV_HEIGHT, Dft_Size, NULL);
  113.     dpy = (Display *) xv_get(ip->window1, XV_DISPLAY);
  114.     screen = (Xv_Screen) xv_get(ip->window1, XV_SCREEN);
  115.     screen_no = (int) xv_get(screen, SCREEN_NUMBER);
  116.     swidth = DisplayWidth(dpy, screen_no);
  117.     sheight = DisplayHeight(dpy, screen_no);
  118.  
  119.     ip->controls1 = xv_create(ip->window1, PANEL, XV_KEY_DATA,
  120.         INSTANCE, ip, XV_HELP_DATA, "workman:controls1",
  121.         XV_WIDTH, 10, XV_HEIGHT, 10, WIN_BORDER,
  122.         FALSE, NULL);
  123.  
  124.     /* Create a dummy message item to get spacing information. */
  125.     item = xv_create(ip->controls1, PANEL_MESSAGE,
  126.         PANEL_LABEL_STRING, " ", PANEL_LABEL_BOLD, TRUE, NULL);
  127.     if (! basic_spacing)
  128.         basic_spacing = hei(item) / 2;
  129.     xv_destroy(item);
  130.  
  131.     if (basic_spacing < 7)
  132.         small_buttons = 1;
  133.     else
  134.         small_buttons = 0;
  135.     small_buttons = defaults_get_boolean("workman.smallButtons",
  136.         "Workman.SmallButtons", small_buttons);
  137.  
  138.     ip->tracks = xv_create(ip->controls1, PANEL_CHOICE,
  139.         XV_HELP_DATA, "workman:tracks",
  140.         XV_X, 10, XV_Y, 10 + basic_spacing * 2,
  141.         PANEL_LAYOUT, PANEL_HORIZONTAL, PANEL_CHOOSE_NONE, FALSE,
  142.         PANEL_NOTIFY_PROC, change_track, NULL);
  143.  
  144.     ip->tracktimer = xv_create(ip->controls1, PANEL_MESSAGE,
  145.         XV_HELP_DATA, "workman:tracktimer",
  146.         XV_X, 6, PANEL_LABEL_STRING, "00:00", PANEL_LABEL_BOLD,
  147.         FALSE, NULL);
  148.     put_down(ip->tracktimer, ip->tracks, basic_spacing * 2);
  149.  
  150.     ip->songpos = xv_create(ip->controls1, PANEL_SLIDER,
  151.         XV_HELP_DATA, "workman:songpos",
  152.         PANEL_TICKS, 0,
  153.         PANEL_DIRECTION, PANEL_HORIZONTAL,
  154.         PANEL_SLIDER_END_BOXES, FALSE,
  155.         PANEL_SHOW_RANGE, FALSE,
  156.         PANEL_SHOW_VALUE, FALSE,
  157.         PANEL_MIN_VALUE, 0,
  158.         PANEL_MAX_VALUE, 100,
  159.         PANEL_VALUE, 0,
  160.         PANEL_INACTIVE, TRUE,
  161.         PANEL_NOTIFY_PROC, change_pos,
  162.         NULL);
  163.     xv_set(ip->songpos, XV_Y, top(ip->tracktimer), NULL);
  164.     put_right(ip->songpos, ip->tracktimer, 10);
  165.  
  166.     ip->tracklen = xv_create(ip->controls1, PANEL_MESSAGE,
  167.         XV_HELP_DATA, "workman:tracklen",
  168.         XV_Y, top(ip->tracktimer),
  169.         PANEL_LABEL_STRING, "00:00",
  170.         PANEL_LABEL_BOLD, FALSE,
  171.         NULL);
  172.  
  173.     speaker_image = xv_create(XV_NULL, SERVER_IMAGE,
  174.         SERVER_IMAGE_DEPTH, 1,
  175.         SERVER_IMAGE_BITS, speaker_bits,
  176.         XV_WIDTH, 16,
  177.         XV_HEIGHT, 15,
  178.         NULL);
  179.     ip->speaker = xv_create(ip->controls1, PANEL_MESSAGE,
  180.         XV_HELP_DATA, "workman:speaker",
  181.         XV_X, 12,
  182.         PANEL_LABEL_IMAGE, speaker_image,
  183.         PANEL_LABEL_BOLD, TRUE,
  184.         NULL);
  185.     put_down(ip->speaker, ip->tracktimer, basic_spacing);
  186.  
  187.     ip->volume = xv_create(ip->controls1, PANEL_SLIDER,
  188.         XV_HELP_DATA, "workman:volume",
  189.         XV_X, 10,
  190.         PANEL_TICKS, 0, PANEL_DIRECTION, PANEL_VERTICAL,
  191.         PANEL_SLIDER_END_BOXES, FALSE, PANEL_SHOW_RANGE, FALSE,
  192.         PANEL_SHOW_VALUE, FALSE, PANEL_MIN_VALUE, 0,
  193.         PANEL_MAX_VALUE, 32, PANEL_VALUE, 0,
  194.         PANEL_NOTIFY_PROC, set_volume, NULL);
  195.     put_down(ip->volume, ip->speaker, 3);
  196.  
  197.     mode_image0 = xv_create(XV_NULL, SERVER_IMAGE,
  198.         SERVER_IMAGE_DEPTH, 1,
  199.         SERVER_IMAGE_BITS, small_buttons ? small_bits0 : mode_bits0,
  200.         XV_WIDTH, small_buttons ? 16 : 32,
  201.         XV_HEIGHT, 16,
  202.         NULL);
  203.     mode_image1 = xv_create(XV_NULL, SERVER_IMAGE,
  204.         SERVER_IMAGE_DEPTH, 1,
  205.         SERVER_IMAGE_BITS, small_buttons ? small_bits1 : mode_bits1,
  206.         XV_WIDTH, small_buttons ? 16 : 32,
  207.         XV_HEIGHT, 16,
  208.         NULL);
  209.     mode_image2 = xv_create(XV_NULL, SERVER_IMAGE,
  210.         SERVER_IMAGE_DEPTH, 1,
  211.         SERVER_IMAGE_BITS, small_buttons ? small_bits2 : mode_bits2,
  212.         XV_WIDTH, small_buttons ? 16 : 32,
  213.         XV_HEIGHT, 16,
  214.         NULL);
  215.     mode_image3 = xv_create(XV_NULL, SERVER_IMAGE,
  216.         SERVER_IMAGE_DEPTH, 1,
  217.         SERVER_IMAGE_BITS, small_buttons ? small_bits3 : mode_bits3,
  218.         XV_WIDTH, small_buttons ? 16 : 32,
  219.         XV_HEIGHT, 16,
  220.         NULL);
  221.     mode_image4 = xv_create(XV_NULL, SERVER_IMAGE,
  222.         SERVER_IMAGE_DEPTH, 1,
  223.         SERVER_IMAGE_BITS, small_buttons ? small_bits4 : mode_bits4,
  224.         XV_WIDTH, small_buttons ? 16 : 32,
  225.         XV_HEIGHT, 16,
  226.         NULL);
  227.     mode_image5 = xv_create(XV_NULL, SERVER_IMAGE,
  228.         SERVER_IMAGE_DEPTH, 1,
  229.         SERVER_IMAGE_BITS, small_buttons ? small_bits5 : mode_bits5,
  230.         XV_WIDTH, small_buttons ? 16 : 32,
  231.         XV_HEIGHT, 16,
  232.         NULL);
  233.     ip->mode = xv_create(ip->controls1, PANEL_CHOICE,
  234.         XV_HELP_DATA, "workman:mode",
  235.         PANEL_CHOICE_NROWS, 2,
  236.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  237.         PANEL_CHOOSE_NONE, FALSE,
  238.         PANEL_NOTIFY_PROC, change_mode,
  239.         PANEL_CHOICE_IMAGES,
  240.             mode_image0,
  241.             mode_image1,
  242.             mode_image2,
  243.             mode_image3,
  244.             mode_image4,
  245.             mode_image5,
  246.             NULL,
  247.         PANEL_VALUE, 4,
  248.         NULL);
  249.     put_right(ip->mode, ip->speaker, 8);
  250.     xv_set(ip->mode, XV_Y, (bot(ip->speaker) + top(ip->speaker)) / 2, NULL);
  251.  
  252.     /* Align the volume slider with the mode selector. */
  253.     xv_set(ip->volume, PANEL_SLIDER_WIDTH, bot(ip->mode) - top(ip->volume) -
  254.         10, NULL);
  255.  
  256.     ip->repeat = xv_create(ip->controls1, PANEL_CHOICE,
  257.         PANEL_DISPLAY_LEVEL, PANEL_CURRENT,
  258.         XV_HELP_DATA, "workman:repeat",
  259.         XV_Y, top(ip->mode),
  260.         PANEL_CHOICE_NCOLS, 1,
  261.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  262.         PANEL_NOTIFY_PROC, next_stopmode,
  263.         PANEL_CHOICE_STRINGS,
  264.             "Stop",
  265.             "Repeat",
  266.             "Eject",
  267.             NULL,
  268.         PANEL_DEFAULT_VALUE, 0,
  269.         NULL);
  270.     put_right(ip->repeat, ip->mode, 8);
  271.  
  272.     ip->shuffle = xv_create(ip->controls1, PANEL_CHOICE,
  273.         PANEL_DISPLAY_LEVEL, PANEL_CURRENT,
  274.         XV_HELP_DATA, "workman:shuffle",
  275.         XV_X, lef(ip->repeat),
  276.         PANEL_CHOICE_NCOLS, 1,
  277.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  278.         PANEL_NOTIFY_PROC, next_playmode_default,
  279.         PANEL_CHOICE_STRINGS,
  280.             "Normal",
  281.             "Shuffle",
  282.             NULL,
  283.         PANEL_DEFAULT_VALUE, 0,
  284.         NULL);
  285.     put_down(ip->shuffle, ip->repeat, 0);
  286.  
  287.     ip->button3 = xv_create(ip->controls1, PANEL_BUTTON,
  288.         XV_HELP_DATA, "workman:button3",
  289.         PANEL_LABEL_STRING, "About...",
  290.         PANEL_NOTIFY_PROC, window1_button3_notify_callback,
  291.         NULL);
  292.  
  293.     ip->button2 = xv_create(ip->controls1, PANEL_BUTTON,
  294.         XV_HELP_DATA, "workman:button2",
  295.         PANEL_LABEL_STRING, "CD Info...",
  296.         PANEL_NOTIFY_PROC, window1_button2_notify_callback,
  297.         NULL);
  298.     
  299.     ip->button4 = xv_create(ip->controls1, PANEL_BUTTON,
  300.         XV_HELP_DATA, "workman:button4",
  301.         PANEL_LABEL_STRING, "Goodies...",
  302.         PANEL_NOTIFY_PROC, window1_button4_notify_callback,
  303.         NULL);
  304.  
  305.     /* Now we can figure out how wide the window should be. */
  306.     space = wid(ip->button2) + wid(ip->button3) + wid(ip->button4);
  307.     if (rig(ip->shuffle) > space)
  308.         xv_set(ip->controls1, XV_WIDTH, rig(ip->shuffle) + 7, NULL);
  309.     else
  310.     {
  311.         xv_set(ip->controls1, XV_WIDTH, space + 10, NULL);
  312.         xv_set(ip->shuffle, XV_X, space - wid(ip->shuffle) + 10, NULL);
  313.         xv_set(ip->repeat, XV_X, lef(ip->shuffle), NULL);
  314.         xv_set(ip->mode, XV_X, (lef(ip->shuffle) - rig(ip->volume) -
  315.             wid(ip->mode)) / 2 + rig(ip->volume), NULL);
  316.     }
  317.  
  318.     /* And knowing that, we can position the songpos slider. */
  319.     xv_set(ip->tracklen, XV_X, wid(ip->controls1) - wid(ip->tracklen) -
  320.         10, NULL);
  321.     xv_set(ip->songpos, PANEL_SLIDER_WIDTH, lef(ip->tracklen) -
  322.         lef(ip->songpos) - 20, NULL);
  323.  
  324.     ip->cdtimer = xv_create(ip->controls1, PANEL_MESSAGE,
  325.         XV_HELP_DATA, "workman:cdtimer",
  326.         PANEL_LABEL_STRING, "00:00",
  327.         XV_X, lef(ip->tracktimer), PANEL_LABEL_BOLD, FALSE, NULL);
  328.     put_down(ip->cdtimer, ip->volume, basic_spacing / 2 + 1);
  329.  
  330.     ip->cdlen = xv_create(ip->controls1, PANEL_MESSAGE,
  331.         XV_HELP_DATA, "workman:cdlen",
  332.         XV_Y, top(ip->cdtimer), XV_X, lef(ip->tracklen),
  333.         PANEL_LABEL_BOLD, FALSE,
  334.         NULL);
  335.  
  336.     ip->cdgauge = xv_create(ip->controls1, PANEL_GAUGE,
  337.         XV_HELP_DATA, "workman:cdgauge",
  338.         XV_X, lef(ip->songpos) - 2, XV_Y, top(ip->cdtimer) + 2,
  339.         PANEL_GAUGE_WIDTH, xv_get(ip->songpos, PANEL_SLIDER_WIDTH) - 5,
  340.         PANEL_TICKS, 0,
  341.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  342.         PANEL_DIRECTION, PANEL_HORIZONTAL,
  343.         PANEL_SHOW_RANGE, FALSE,
  344.         PANEL_MIN_VALUE, 0,
  345.         PANEL_MAX_VALUE, 100,
  346.         PANEL_VALUE, 0,
  347.         PANEL_INACTIVE, TRUE,
  348.         NULL);
  349.  
  350.     space = (wid(ip->controls1) - space) / 4;
  351.     xv_set(ip->button3, XV_X, space, XV_Y, bot(ip->cdtimer) +
  352.         basic_spacing, NULL);
  353.     xv_set(ip->button2, XV_X, rig(ip->button3) + space, XV_Y,
  354.         top(ip->button3), NULL);
  355.     xv_set(ip->button4, XV_X, rig(ip->button2) + space, XV_Y,
  356.         top(ip->button3), NULL);
  357.  
  358.     xv_set(ip->controls1, XV_HEIGHT, bot(ip->button2) + 5, NULL);
  359.     window_fit(ip->window1);
  360.  
  361.     PANEL_EACH_ITEM(ip->controls1, item)
  362.         xv_set(item, XV_KEY_DATA, INSTANCE, ip, NULL);
  363.     PANEL_END_EACH;
  364.  
  365.     /*
  366.      * Now adjust the window's position in case it was started with
  367.      * -geometry -0+10 or similar.  Unfortunately, to do this we have
  368.      * to make assumptions about the window manager's decorations.
  369.      */
  370.     space = (int) xv_get(ip->window1, XV_WIDTH);
  371.     x = (int) xv_get(ip->window1, XV_X);
  372.     if (space + x > swidth)
  373.         xv_set(ip->window1, XV_X, x + Dft_Size - space, NULL);
  374.     space = (int) xv_get(ip->window1, XV_HEIGHT);
  375.     x = (int) xv_get(ip->window1, XV_Y);
  376.     if (space + x > sheight)
  377.         xv_set(ip->window1, XV_Y, x + Dft_Size - space, NULL);
  378.  
  379.     return (ip);
  380. }
  381.  
  382. /*
  383.  * Set up the CD Info popup.
  384.  */
  385. popup1_objects *
  386. popup1_objects_init(ip, owner)
  387.     popup1_objects    *ip;
  388.     Xv_opaque        owner;
  389. {
  390.     int    space, spwidth, zerowidth;
  391.     Xv_Font    font;
  392.     Panel_item item;
  393.  
  394.     if ((ip = (popup1_objects *) calloc(1,
  395.                 sizeof(window1_objects))) == NULL)
  396.         return (NULL);
  397.  
  398.     ip->popup1 = xv_create(owner, FRAME_CMD,
  399.         XV_KEY_DATA, INSTANCE, ip,
  400.         XV_LABEL, "CD Information",
  401.         XV_SHOW, FALSE,
  402.         FRAME_SHOW_FOOTER, FALSE,
  403.         FRAME_SHOW_RESIZE_CORNER, FALSE,
  404.         FRAME_CMD_PUSHPIN_IN, TRUE,
  405.         NULL);
  406.     xv_set(xv_get(ip->popup1, FRAME_CMD_PANEL), WIN_SHOW, FALSE, NULL);
  407.  
  408.     ip->controls2 = xv_create(ip->popup1, PANEL,
  409.         XV_KEY_DATA, INSTANCE, ip,
  410.         XV_HELP_DATA, "workman:controls2",
  411.         XV_X, 0,
  412.         XV_Y, 0,
  413.         XV_WIDTH, 10000,
  414.         XV_HEIGHT, 10000,
  415.         WIN_BORDER, FALSE,
  416.         NULL);
  417.  
  418.     /*
  419.      * In order to properly do spacing on the track list, we need to
  420.      * determine the width of spaces and digits.  In most fonts, a space
  421.      * is half the width of a digit.  But in monospace fonts the widths
  422.      * are the same.
  423.      */
  424.     font = (Xv_Font) xv_get(ip->controls2, XV_FONT);
  425.     spwidth = xv_get(font, FONT_CHAR_WIDTH, ' ');
  426.     zerowidth = xv_get(font, FONT_CHAR_WIDTH, '0');
  427.  
  428.     if (spwidth == zerowidth)
  429.         big_spaces = 1;
  430.  
  431.     ip->artist = xv_create(ip->controls2, PANEL_TEXT,
  432.         XV_HELP_DATA, "workman:artist",
  433.         XV_Y, 8,
  434.         PANEL_VALUE_DISPLAY_LENGTH, 30,
  435.         PANEL_VALUE_STORED_LENGTH, 80,
  436.         PANEL_LABEL_STRING, "Artist:",
  437.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  438.         PANEL_READ_ONLY, FALSE,
  439.         PANEL_NOTIFY_PROC, update_title,
  440.         NULL);
  441.  
  442.     ip->cdname = xv_create(ip->controls2, PANEL_TEXT,
  443.         XV_HELP_DATA, "workman:cdname",
  444.         XV_X, 10,
  445.         PANEL_VALUE_DISPLAY_LENGTH, 30,
  446.         PANEL_VALUE_STORED_LENGTH, 80,
  447.         PANEL_LABEL_STRING, "Disc Title:",
  448.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  449.         PANEL_READ_ONLY, FALSE,
  450.         PANEL_NOTIFY_PROC, update_title,
  451.         NULL);
  452.     put_down(ip->cdname, ip->artist, basic_spacing);
  453.  
  454.     xv_set(ip->artist, PANEL_VALUE_X, (int) xv_get(ip->cdname,
  455.         PANEL_VALUE_X), NULL);
  456.  
  457.     ip->tracklist = xv_create(ip->controls2, PANEL_LIST,
  458.         XV_HELP_DATA, "workman:tracklist",
  459.         XV_X, 4,
  460.         PANEL_LIST_DISPLAY_ROWS, 6,
  461.         PANEL_LIST_TITLE, "Tracks",
  462.         PANEL_LAYOUT, PANEL_VERTICAL,
  463.         PANEL_READ_ONLY, TRUE,
  464.         PANEL_CHOOSE_ONE, TRUE,
  465.         PANEL_CHOOSE_NONE, TRUE,
  466.         PANEL_INACTIVE, TRUE,
  467.         PANEL_NOTIFY_PROC, update_trackname,
  468.         NULL);
  469.     put_down(ip->tracklist, ip->cdname, basic_spacing);
  470.  
  471.     ip->trackname = xv_create(ip->controls2, PANEL_TEXT,
  472.         XV_HELP_DATA, "workman:trackname",
  473.         XV_X, 5,
  474.         PANEL_VALUE_DISPLAY_LENGTH, 35,
  475.         PANEL_VALUE_STORED_LENGTH, 500,
  476.         PANEL_LABEL_STRING, "Name:",
  477.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  478.         PANEL_INACTIVE, TRUE,
  479.         PANEL_READ_ONLY, FALSE,
  480.         PANEL_NOTIFY_PROC, name_entered,
  481.         NULL);
  482.     put_down(ip->trackname, ip->tracklist, basic_spacing);
  483.  
  484.     xv_set(ip->tracklist, PANEL_LIST_WIDTH, wid(ip->trackname) + 10, NULL);
  485.  
  486.     ip->trackoptions = xv_create(ip->controls2, PANEL_TOGGLE,
  487.         XV_HELP_DATA, "workman:trackoptions",
  488.         PANEL_CHOICE_NCOLS, 1,
  489.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  490.         PANEL_CHOICE_STRINGS,
  491.             "Continuation of previous track",
  492.             "Don't play this track",
  493.             NULL,
  494.         PANEL_VALUE, 0,
  495.         PANEL_INACTIVE, TRUE,
  496.         NULL);
  497.     put_down(ip->trackoptions, ip->trackname, 5);
  498.  
  499.     ip->whichvolume = xv_create(ip->controls2, PANEL_CHOICE,
  500.         PANEL_DISPLAY_LEVEL, PANEL_CURRENT,
  501.         XV_HELP_DATA, "workman:whichvolume",
  502.         PANEL_CHOICE_NROWS, 1,
  503.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  504.         PANEL_LABEL_STRING, "Default Volume for this",
  505.         PANEL_NOTIFY_PROC, set_which_volume,
  506.         PANEL_CHOICE_STRINGS,
  507.             "Disc",
  508.             "Track",
  509.             NULL,
  510.         PANEL_DEFAULT_VALUE, 0,
  511.         NULL);
  512.     put_down(ip->whichvolume, ip->trackoptions, 5);
  513.  
  514.     ip->defaultvolume = xv_create(ip->controls2, PANEL_SLIDER,
  515.         XV_HELP_DATA, "workman:defaultvolume",
  516.         PANEL_SLIDER_WIDTH, 2,
  517.         PANEL_TICKS, 0,
  518.         PANEL_DIRECTION, PANEL_HORIZONTAL,
  519.         PANEL_SLIDER_END_BOXES, FALSE,
  520.         PANEL_SHOW_RANGE, FALSE,
  521.         PANEL_SHOW_VALUE, FALSE,
  522.         PANEL_MIN_VALUE, 0,
  523.         PANEL_MAX_VALUE, 32,
  524.         PANEL_VALUE, 0,
  525.         PANEL_NOTIFY_PROC, set_default_volume,
  526.         NULL);
  527.  
  528.     /* This will get changed to an image later, but use text for now */
  529.     ip->defaultspeaker = xv_create(ip->controls2, PANEL_MESSAGE,
  530.         XV_HELP_DATA, "workman:defaultspeaker",
  531.         PANEL_LABEL_STRING, "None",
  532.         PANEL_LABEL_BOLD, FALSE,
  533.         XV_SHOW, FALSE,
  534.         NULL);
  535.  
  536.     ip->nonemsg = xv_create(ip->controls2, PANEL_MESSAGE,
  537.         XV_HELP_DATA, "workman:defaultspeaker",
  538.         PANEL_LABEL_STRING, "None",
  539.         PANEL_LABEL_BOLD, FALSE,
  540.         XV_X, xv_get(ip->defaultspeaker, XV_X),
  541.         NULL);
  542.  
  543.     space = wid(ip->whichvolume) + wid(ip->defaultspeaker) * 2 +
  544.         wid(ip->defaultvolume) + 20;
  545.     if (space > wid(ip->tracklist))
  546.     {
  547.         xv_set(ip->controls2, XV_WIDTH, space + 10, NULL);
  548.         xv_set(ip->tracklist, PANEL_LIST_WIDTH, space + 3 -
  549.             wid(ip->tracklist) + (int) xv_get(ip->tracklist,
  550.             PANEL_LIST_WIDTH), NULL);
  551.     }
  552.     else
  553.     {
  554.         xv_set(ip->controls2, XV_WIDTH, wid(ip->tracklist) + 7, NULL);
  555.         space += 20;
  556.     }
  557.  
  558.     center_x(ip->trackoptions, ip->controls2);
  559.  
  560.     space = (wid(ip->controls2) - space) / 2;
  561.     xv_set(ip->whichvolume, XV_X, space, NULL);
  562.     xv_set(ip->defaultvolume, XV_X, rig(ip->whichvolume),
  563.         PANEL_SLIDER_WIDTH, wid(ip->defaultspeaker) * 2 - 15,
  564.         XV_Y, (top(ip->whichvolume) + bot(ip->whichvolume) -
  565.         hei(ip->defaultvolume)) / 2 + 2, NULL);
  566.     xv_set(ip->defaultspeaker, XV_X, rig(ip->defaultvolume) + 5,
  567.         XV_Y, top(ip->defaultspeaker) + hei(ip->defaultvolume) / 6,
  568.         NULL);
  569.     xv_set(ip->nonemsg, XV_X, xv_get(ip->defaultspeaker, XV_X),
  570.         XV_Y, xv_get(ip->defaultspeaker, XV_Y),
  571.         NULL);
  572.  
  573.     ip->playmode = xv_create(ip->controls2, PANEL_CHOICE,
  574.         XV_HELP_DATA, "workman:playmode",
  575.         XV_X, lef(ip->whichvolume),
  576.         PANEL_CHOICE_NROWS, 1,
  577.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  578.         PANEL_CHOOSE_NONE, FALSE,
  579.         PANEL_LABEL_STRING, "Default Play Mode",
  580.         PANEL_CHOICE_STRINGS,
  581.             "Normal",
  582.             "Shuffle",
  583.             "From List",
  584.             NULL,
  585.         NULL);
  586.     put_down(ip->playmode, ip->defaultvolume, basic_spacing / 2);
  587.  
  588.     ip->autoplay = xv_create(ip->controls2, PANEL_TOGGLE,
  589.         XV_HELP_DATA, "workman:autoplay",
  590.         PANEL_CHOICE_NCOLS, 1,
  591.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  592.         PANEL_CHOICE_STRING, 0, "Play this CD automatically",
  593.         PANEL_VALUE, 0,
  594.         NULL);
  595.     put_down(ip->autoplay, ip->playmode, basic_spacing / 2);
  596.     center_x(ip->autoplay, ip->controls2);
  597.  
  598.     ip->button1 = xv_create(ip->controls2, PANEL_BUTTON,
  599.         XV_HELP_DATA, "workman:button1",
  600.         PANEL_LABEL_STRING, "Apply",
  601.         PANEL_NOTIFY_PROC, save_config,
  602.         NULL);
  603.     put_down(ip->button1, ip->autoplay, (basic_spacing * 3) / 2);
  604.     xv_set(ip->button1, XV_X, wid(ip->controls2) / 2 - wid(ip->button1) - 5,
  605.         NULL);
  606.  
  607.     ip->button8 = xv_create(ip->controls2, PANEL_BUTTON,
  608.         XV_HELP_DATA, "workman:button8",
  609.         XV_X, rig(ip->button1) + 10,
  610.         XV_Y, top(ip->button1),
  611.         PANEL_LABEL_STRING, "Reset",
  612.         PANEL_NOTIFY_PROC, cdinfo_reset,
  613.         NULL);
  614.  
  615.     ip->buttonpl = xv_create(ip->controls2, PANEL_BUTTON,
  616.         XV_HELP_DATA, "workman:buttonpl",
  617.         XV_Y, top(ip->button1),
  618.         PANEL_LABEL_STRING, "Playlists...",
  619.         PANEL_NOTIFY_PROC, popup1_buttonpl_notify_callback,
  620.         NULL);
  621.     xv_set(ip->buttonpl, XV_X, wid(ip->controls2) - wid(ip->buttonpl) - 10,
  622.         NULL);
  623.  
  624.     xv_set(ip->controls2, XV_HEIGHT, bot(ip->button1) + 5, NULL);
  625.     window_fit(ip->popup1);
  626.  
  627.     PANEL_EACH_ITEM(ip->controls2, item)
  628.         xv_set(item, XV_KEY_DATA, INSTANCE, ip, NULL);
  629.     PANEL_END_EACH;
  630.  
  631.     return (ip);
  632. }
  633.  
  634. /*
  635.  * Create the About window and its contents.
  636.  */
  637. about_objects *
  638. about_objects_init(ip, owner)
  639.     about_objects    *ip;
  640.     Xv_opaque        owner;
  641. {
  642.     Panel_item    item;
  643.     int        space;
  644.     Xv_opaque               sink_image, message7_image;
  645.     static unsigned short   sink_bits[] = {
  646. #include "bitmaps/sink0"
  647.     };
  648.  
  649.     if ((ip = (about_objects *) calloc(1,
  650.                 sizeof(about_objects))) == NULL)
  651.         return (NULL);
  652.  
  653.     ip->about = xv_create(owner, FRAME_CMD,
  654.         XV_KEY_DATA, INSTANCE, ip,
  655.         XV_LABEL, "About WorkMan",
  656.         XV_SHOW, FALSE,
  657.         FRAME_SHOW_FOOTER, FALSE,
  658.         FRAME_SHOW_RESIZE_CORNER, FALSE,
  659.         FRAME_CMD_PUSHPIN_IN, TRUE,
  660.         NULL);
  661.     xv_set(xv_get(ip->about, FRAME_CMD_PANEL), WIN_SHOW, FALSE, NULL);
  662.  
  663.     ip->controls3 = xv_create(ip->about, PANEL,
  664.         XV_KEY_DATA, INSTANCE, ip,
  665.         XV_HELP_DATA, "workman:controls3",
  666.         XV_X, 0,
  667.         XV_Y, 0,
  668.         WIN_BORDER, FALSE,
  669.         NULL);
  670.  
  671.     ip->message1 = xv_create(ip->controls3, PANEL_MESSAGE,
  672.         XV_Y, 8,
  673.         PANEL_LABEL_STRING, "WorkMan 1.2.2a",
  674.         PANEL_LABEL_BOLD, TRUE, NULL);
  675.     ip->message2 = xv_create(ip->controls3, PANEL_MESSAGE,
  676.         PANEL_LABEL_STRING, "\"The Civilized CD Player\"",
  677.         PANEL_LABEL_BOLD, FALSE, NULL);
  678.  
  679.     message7_image = xv_create(XV_NULL, SERVER_IMAGE,
  680.         SERVER_IMAGE_DEPTH, 1,
  681.         SERVER_IMAGE_BITS, bits,
  682.         XV_WIDTH, 64,
  683.         XV_HEIGHT, 64,
  684.         NULL);
  685.     ip->message7 = xv_create(ip->controls3, PANEL_MESSAGE,
  686.         XV_KEY_DATA, INSTANCE, ip,
  687.         PANEL_LABEL_IMAGE, message7_image,
  688.         PANEL_LABEL_BOLD, TRUE,
  689.         NULL);
  690.  
  691.     sink_image = xv_create(XV_NULL, SERVER_IMAGE,
  692.         SERVER_IMAGE_DEPTH, 1,
  693.         SERVER_IMAGE_BITS, sink_bits,
  694.         XV_WIDTH, 64,
  695.         XV_HEIGHT, 64,
  696.         NULL);
  697.     ip->sink = xv_create(ip->controls3, PANEL_MESSAGE,
  698.         XV_HELP_DATA, "workman:sink",
  699.         PANEL_LABEL_IMAGE, sink_image,
  700.         PANEL_LABEL_BOLD, TRUE,
  701.         NULL);
  702.  
  703.     ip->message3 = xv_create(ip->controls3, PANEL_MESSAGE,
  704.         PANEL_LABEL_STRING, "Written by Steven Grimm",
  705.         PANEL_LABEL_BOLD, TRUE, NULL);
  706.     ip->message4 = xv_create(ip->controls3, PANEL_MESSAGE,
  707.         PANEL_LABEL_STRING, "koreth@Hyperion.COM",
  708.         PANEL_LABEL_BOLD, FALSE, NULL);
  709.     ip->message5 = xv_create(ip->controls3, PANEL_MESSAGE,
  710.         PANEL_LABEL_STRING, "Send mail if you'd like to be",
  711.         PANEL_LABEL_BOLD, FALSE, NULL);
  712.     ip->message6 = xv_create(ip->controls3, PANEL_MESSAGE,
  713.         PANEL_LABEL_STRING, "notified of future revisions!",
  714.         PANEL_LABEL_BOLD, FALSE, NULL);
  715.  
  716.     ip->drive = xv_create(ip->controls3, PANEL_MESSAGE,
  717.         PANEL_LABEL_STRING, "MMMMMMMM MMMMMMMMM",
  718.         PANEL_LABEL_BOLD, FALSE,
  719.         NULL);
  720.  
  721.     space = 0;
  722.     PANEL_EACH_ITEM(ip->controls3, item)
  723.         xv_set(item, XV_KEY_DATA, INSTANCE, ip, NULL);
  724.         if (wid(item) > space)
  725.             space = wid(item);
  726.     PANEL_END_EACH;
  727.  
  728.     xv_set(ip->drive, PANEL_LABEL_STRING, "Unknown drive type", NULL);
  729.  
  730.     space += 10;
  731.     xv_set(ip->controls3, XV_WIDTH, space, NULL);
  732.     center_x(ip->message1, ip->controls3);
  733.     center_x(ip->message2, ip->controls3);
  734.     center_x(ip->message3, ip->controls3);
  735.     center_x(ip->message4, ip->controls3);
  736.     center_x(ip->message5, ip->controls3);
  737.     center_x(ip->message6, ip->controls3);
  738.     center_x(ip->drive, ip->controls3);
  739.     xv_set(ip->message7, XV_X, space / 2 - wid(ip->message7) - 5, NULL);
  740.  
  741.     put_down(ip->message2, ip->message1, basic_spacing);
  742.     put_down(ip->message7, ip->message2, basic_spacing);
  743.     xv_set(ip->sink, XV_X, space / 2 + 5, XV_Y, top(ip->message7), NULL);
  744.     put_down(ip->message3, ip->sink, basic_spacing);
  745.     put_down(ip->message4, ip->message3, basic_spacing);
  746.     put_down(ip->message5, ip->message4, basic_spacing * 2);
  747.     put_down(ip->message6, ip->message5, basic_spacing);
  748.     put_down(ip->drive, ip->message6, basic_spacing * 2);
  749.  
  750.     xv_set(ip->controls3, XV_HEIGHT, bot(ip->drive) + 5, NULL);
  751.     window_fit(ip->about);
  752.  
  753.     return (ip);
  754. }
  755.  
  756. /*
  757.  * We've discovered the drive type, so update the About popup.
  758.  */
  759. void
  760. about_set_drivetype(vendor, model, rev)
  761.     char    *vendor, *model, *rev;
  762. {
  763.     extern about_objects    *Workman_about;
  764.     char            drivetype[21];
  765.  
  766.     sprintf(drivetype, "%s %s", vendor, model);
  767.     xv_set(Workman_about->drive, PANEL_LABEL_STRING, drivetype, NULL);
  768.     center_x(Workman_about->drive, Workman_about->controls3);
  769. }
  770.  
  771. /*
  772.  * Create the Goodies window and its contents.
  773.  */
  774. goodies_objects *
  775. goodies_objects_init(ip, owner)
  776.     goodies_objects    *ip;
  777.     Xv_opaque        owner;
  778. {
  779.     Panel_item    item;
  780.     Xv_opaque    phones_image;
  781.     static unsigned short phones_bits[] = {
  782. #include "bitmaps/phones0"
  783.     };
  784.     int        space;
  785.  
  786.     if ((ip = (goodies_objects *) calloc(1,
  787.                 sizeof(goodies_objects))) == NULL)
  788.         return (NULL);
  789.  
  790.     ip->goodies = xv_create(owner, FRAME_CMD,
  791.         XV_KEY_DATA, INSTANCE, ip,
  792.         XV_LABEL, "Goodies",
  793.         XV_SHOW, FALSE,
  794.         FRAME_SHOW_FOOTER, FALSE,
  795.         FRAME_SHOW_RESIZE_CORNER, FALSE,
  796.         FRAME_CMD_PUSHPIN_IN, TRUE,
  797.         NULL);
  798.     xv_set(xv_get(ip->goodies, FRAME_CMD_PANEL), WIN_SHOW, FALSE, NULL);
  799.  
  800.     ip->controls4 = xv_create(ip->goodies, PANEL,
  801.         XV_KEY_DATA, INSTANCE, ip,
  802.         XV_HELP_DATA, "workman:controls4",
  803.         XV_X, 0,
  804.         XV_Y, 0,
  805.         WIN_BORDER, FALSE,
  806.         NULL);
  807.  
  808.     ip->balance = xv_create(ip->controls4, PANEL_SLIDER,
  809.         XV_HELP_DATA, "workman:balance",
  810.         XV_Y, 6,
  811.         PANEL_SLIDER_WIDTH, basic_spacing * 5,
  812.         PANEL_TICKS, 3,
  813.         PANEL_LABEL_STRING, "Balance:",
  814.         PANEL_DIRECTION, PANEL_HORIZONTAL,
  815.         PANEL_SLIDER_END_BOXES, FALSE,
  816.         PANEL_SHOW_RANGE, FALSE,
  817.         PANEL_SHOW_VALUE, FALSE,
  818.         PANEL_MIN_VALUE, 0,
  819.         PANEL_MAX_VALUE, 20,
  820.         PANEL_VALUE, 10,
  821.         PANEL_NOTIFY_PROC, slide_balance,
  822.         NULL);
  823.  
  824.     phones_image = xv_create(XV_NULL, SERVER_IMAGE,
  825.         SERVER_IMAGE_DEPTH, 1,
  826.         SERVER_IMAGE_BITS, phones_bits,
  827.         XV_WIDTH, 16,
  828.         XV_HEIGHT, 22,
  829.         NULL);
  830.     ip->phones = xv_create(ip->controls4, PANEL_MESSAGE,
  831.         XV_HELP_DATA, "workman:phones",
  832.         XV_Y, 6,
  833.         PANEL_LABEL_IMAGE, phones_image,
  834.         PANEL_LABEL_BOLD, TRUE,
  835.         NULL);
  836.  
  837.     ip->timemode_track = xv_create(ip->controls4, PANEL_CHOICE,
  838.         XV_HELP_DATA, "workman:timemode",
  839.         PANEL_CHOICE_NROWS, 1,
  840.         PANEL_LAYOUT, PANEL_VERTICAL,
  841.         PANEL_CHOOSE_NONE, FALSE,
  842.         PANEL_LABEL_STRING, "Track time display:",
  843.         PANEL_CHOICE_STRINGS,
  844.             "Elapsed",
  845.             "Remaining",
  846.             NULL,
  847.         PANEL_VALUE, 0,
  848.         NULL);
  849.     put_down(ip->timemode_track, ip->balance, basic_spacing);
  850.  
  851.     ip->timemode_cd = xv_create(ip->controls4, PANEL_CHOICE,
  852.         XV_HELP_DATA, "workman:timemode",
  853.         PANEL_CHOICE_NROWS, 1,
  854.         PANEL_LAYOUT, PANEL_VERTICAL,
  855.         PANEL_CHOOSE_NONE, FALSE,
  856.         PANEL_LABEL_STRING, "CD time display:",
  857.         PANEL_CHOICE_STRINGS,
  858.             "Elapsed",
  859.             "Remaining",
  860.             NULL,
  861.         PANEL_VALUE, 0,
  862.         NULL);
  863.     put_down(ip->timemode_cd, ip->timemode_track, basic_spacing);
  864.  
  865.     ip->playnewcds = xv_create(ip->controls4, PANEL_TOGGLE,
  866.         XV_HELP_DATA, "workman:playnewcds",
  867.         PANEL_CHOICE_NROWS, 1,
  868.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  869.         PANEL_NOTIFY_PROC, goodies_playnewcds_notify_callback,
  870.         PANEL_CHOICE_STRING, 0, "Auto-play unknown CDs",
  871.         PANEL_VALUE, 0,
  872.         NULL);
  873.     put_down(ip->playnewcds, ip->timemode_cd, basic_spacing * 2);
  874.  
  875.     ip->abrepeat = xv_create(ip->controls4, PANEL_TOGGLE,
  876.         XV_HELP_DATA, "workman:abrepeat",
  877.         PANEL_CHOICE_NCOLS, 1,
  878.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  879.         PANEL_NOTIFY_PROC, goodies_abrepeat_notify_callback,
  880.         PANEL_CHOICE_STRING, 0, "Repeat section of CD:",
  881.         PANEL_VALUE, 0,
  882.         NULL);
  883.     put_down(ip->abrepeat, ip->playnewcds, basic_spacing * 2);
  884.  
  885.     ip->a = xv_create(ip->controls4, PANEL_BUTTON,
  886.         XV_HELP_DATA, "workman:a",
  887.         PANEL_LABEL_STRING, "Start",
  888.         PANEL_NOTIFY_PROC, section_start,
  889.         NULL);
  890.     put_down(ip->a, ip->abrepeat, basic_spacing);
  891.  
  892.     ip->alabel = xv_create(ip->controls4, PANEL_MESSAGE,
  893.         XV_HELP_DATA, "workman:alabel",
  894.         PANEL_LABEL_STRING, "Track: 00.00 Time: 00:00",
  895.         PANEL_LABEL_BOLD, FALSE,
  896.         PANEL_INACTIVE, TRUE,
  897.         NULL);
  898.     center_y(ip->alabel, ip->a);
  899.  
  900.     ip->b = xv_create(ip->controls4, PANEL_BUTTON,
  901.         XV_HELP_DATA, "workman:b",
  902.         PANEL_LABEL_STRING, "End",
  903.         PANEL_NOTIFY_PROC, section_end,
  904.         NULL);
  905.     put_down(ip->b, ip->a, basic_spacing / 2);
  906.  
  907.     ip->blabel = xv_create(ip->controls4, PANEL_MESSAGE,
  908.         XV_HELP_DATA, "workman:alabel", 
  909.         PANEL_LABEL_STRING, "Track: 00.00 Time: 00:00",
  910.         PANEL_LABEL_BOLD, FALSE, 
  911.         PANEL_INACTIVE, TRUE, 
  912.         NULL); 
  913.     center_y(ip->blabel, ip->b);
  914.  
  915.     ip->split = xv_create(ip->controls4, PANEL_BUTTON,
  916.         XV_HELP_DATA, "workman:splittrk",
  917.         PANEL_LABEL_STRING, "Split",
  918.         PANEL_NOTIFY_PROC, split_track,
  919.         NULL);
  920.     put_down(ip->split, ip->b, basic_spacing);
  921.  
  922.     ip->delete = xv_create(ip->controls4, PANEL_BUTTON,
  923.         XV_HELP_DATA, "workman:deletetrk",
  924.         PANEL_LABEL_STRING, "Delete",
  925.         PANEL_NOTIFY_PROC, delete_track,
  926.         PANEL_INACTIVE, TRUE,
  927.         NULL);
  928.     put_down(ip->delete, ip->b, basic_spacing);
  929.  
  930.     ip->indexscan = xv_create(ip->controls4, PANEL_BUTTON,
  931.         XV_HELP_DATA, "workman:indexscan",
  932.         PANEL_LABEL_STRING, "Scan for index marks",
  933.         PANEL_NOTIFY_PROC, index_scan,
  934.         NULL);
  935.     put_down(ip->indexscan, ip->split, basic_spacing);
  936.  
  937.     space = wid(ip->a) + wid(ip->alabel) + basic_spacing;
  938.     PANEL_EACH_ITEM(ip->controls4, item)
  939.         xv_set(item, XV_KEY_DATA, INSTANCE, ip, NULL);
  940.         if (wid(item) > space)
  941.             space = wid(item);
  942.     PANEL_END_EACH;
  943.  
  944.     space += 10;
  945.     xv_set(ip->controls4, XV_WIDTH, space, XV_HEIGHT,
  946.         bot(ip->indexscan) + 5, NULL);
  947.     window_fit(ip->goodies);
  948.  
  949.     center_x(ip->timemode_cd, ip->controls4);
  950.     center_x(ip->timemode_track, ip->controls4);
  951.     center_x(ip->playnewcds, ip->controls4);
  952.     center_x(ip->abrepeat, ip->controls4);
  953.     xv_set(ip->balance, XV_X, space / 2 - (wid(ip->balance) +
  954.         wid(ip->phones) + basic_spacing) / 2, NULL);
  955.     put_right(ip->phones, ip->balance, basic_spacing);
  956.     xv_set(ip->a, XV_X, space / 2 - (wid(ip->a) + wid(ip->alabel) +
  957.         basic_spacing) / 2, NULL);
  958.     put_right(ip->alabel, ip->a, basic_spacing);
  959.     center_x(ip->b, ip->a);
  960.     xv_set(ip->blabel, XV_X, lef(ip->alabel), NULL);
  961.  
  962.     space = wid(ip->split) + wid(ip->delete) + basic_spacing * 3;
  963.     space = (wid(ip->controls4) - space) / 2;
  964.     xv_set(ip->split, XV_X, space, NULL);
  965.     put_right(ip->delete, ip->split, basic_spacing * 2);
  966.  
  967.     center_x(ip->indexscan, ip->controls4);
  968.  
  969.     return (ip);
  970. }
  971.  
  972. /*
  973.  * Create the menu for the Playlists popup.
  974.  */
  975. Xv_opaque
  976. trackmenu_create(ip, owner)
  977.     caddr_t         ip;
  978.     Xv_opaque       owner;
  979. {
  980.     Xv_opaque       obj;
  981.  
  982.     obj = xv_create(XV_NULL, MENU_COMMAND_MENU,
  983.         XV_KEY_DATA, INSTANCE, ip,
  984.         MENU_TITLE_ITEM, owner ? "" : "Tracks",
  985.         MENU_GEN_PIN_WINDOW, owner, "Tracks",
  986.         NULL);
  987.     return obj;
  988. }
  989.  
  990. /*
  991.  * Create the Playlists window and its contents.
  992.  */
  993. plpopup_objects *
  994. plpopup_objects_init(ip, owner)
  995.     plpopup_objects    *ip;
  996.     Xv_opaque        owner;
  997. {
  998.     Panel_item    item;
  999.  
  1000.     if ((ip = (plpopup_objects *) calloc(1,
  1001.                 sizeof(plpopup_objects))) == NULL)
  1002.         return (NULL);
  1003.  
  1004.     ip->plpopup = xv_create(owner, FRAME_CMD,
  1005.         XV_KEY_DATA, INSTANCE, ip,
  1006.         XV_LABEL, "Playlists",
  1007.         XV_SHOW, FALSE,
  1008.         FRAME_SHOW_FOOTER, FALSE,
  1009.         FRAME_SHOW_RESIZE_CORNER, FALSE,
  1010.         FRAME_CMD_PUSHPIN_IN, FALSE,
  1011.         NULL);
  1012.     xv_set(xv_get(ip->plpopup, FRAME_CMD_PANEL), WIN_SHOW, FALSE, NULL);
  1013.  
  1014.     ip->controls5 = xv_create(ip->plpopup, PANEL,
  1015.         XV_KEY_DATA, INSTANCE, ip,
  1016.         XV_HELP_DATA, "workman:controls5",
  1017.         XV_X, 0,
  1018.         XV_Y, 0,
  1019.         WIN_BORDER, FALSE,
  1020.         NULL);
  1021.  
  1022.     ip->playlists = xv_create(ip->controls5, PANEL_LIST,
  1023.         XV_HELP_DATA, "workman:playlists",
  1024.         XV_X, 6,
  1025.         XV_Y, 8,
  1026.         PANEL_LIST_WIDTH, basic_spacing * 22,
  1027.         PANEL_LIST_DISPLAY_ROWS, 4,
  1028.         PANEL_LIST_TITLE, "Playlists",
  1029.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  1030.         PANEL_READ_ONLY, TRUE,
  1031.         PANEL_CHOOSE_ONE, TRUE,
  1032.         PANEL_CHOOSE_NONE, FALSE,
  1033.         PANEL_NOTIFY_PROC, switch_playlists,
  1034.         NULL);
  1035.  
  1036.     ip->listname = xv_create(ip->controls5, PANEL_TEXT,
  1037.         XV_HELP_DATA, "workman:listname",
  1038.         XV_Y, 8 + basic_spacing * 2,
  1039.         PANEL_VALUE_DISPLAY_LENGTH, 12,
  1040.         PANEL_VALUE_STORED_LENGTH, 20,
  1041.         PANEL_LABEL_STRING, "Name:",
  1042.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  1043.         PANEL_READ_ONLY, FALSE,
  1044.         NULL);
  1045.     put_right(ip->listname, ip->playlists, basic_spacing);
  1046.  
  1047.     ip->button7 = xv_create(ip->controls5, PANEL_BUTTON,
  1048.         XV_HELP_DATA, "workman:button7",
  1049.         PANEL_LABEL_STRING, "Create new list",
  1050.         PANEL_NOTIFY_PROC, plpopup_button7_notify_callback,
  1051.         NULL);
  1052.     put_down(ip->button7, ip->listname, basic_spacing);
  1053.     center_x(ip->button7, ip->listname);
  1054.  
  1055.     ip->button6 = xv_create(ip->controls5, PANEL_BUTTON,
  1056.         XV_HELP_DATA, "workman:button6",
  1057.         PANEL_LABEL_STRING, "Rename this list",
  1058.         PANEL_NOTIFY_PROC, rename_playlist,
  1059.         NULL);
  1060.     put_down(ip->button6, ip->button7, basic_spacing);
  1061.     center_x(ip->button6, ip->listname);
  1062.  
  1063.     ip->button5 = xv_create(ip->controls5, PANEL_BUTTON,
  1064.         XV_HELP_DATA, "workman:button5",
  1065.         PANEL_LABEL_STRING, "Delete this list",
  1066.         PANEL_NOTIFY_PROC, delete_playlist,
  1067.         NULL);
  1068.     xv_set(ip->button5, XV_Y, bot(ip->playlists) - hei(ip->button5), NULL);
  1069.     center_x(ip->button5, ip->listname);
  1070.  
  1071.     ip->playlist = xv_create(ip->controls5, PANEL_LIST,
  1072.         XV_HELP_DATA, "workman:playlist",
  1073.         XV_X, lef(ip->playlists),
  1074.         PANEL_LIST_WIDTH, rig(ip->listname) - lef(ip->playlists),
  1075.         PANEL_LIST_DISPLAY_ROWS, 5,
  1076.         PANEL_LIST_TITLE, "Playlist (add tracks from popup menu)",
  1077.         PANEL_LAYOUT, PANEL_VERTICAL,
  1078.         PANEL_READ_ONLY, TRUE,
  1079.         PANEL_CHOOSE_ONE, TRUE,
  1080.         PANEL_CHOOSE_NONE, TRUE,
  1081.         PANEL_INACTIVE, TRUE,
  1082.         PANEL_ITEM_MENU,
  1083.             trackmenu_create((caddr_t) ip, ip->plpopup),
  1084.         PANEL_NOTIFY_PROC, playlist_notify,
  1085.         NULL);
  1086.     put_down(ip->playlist, ip->playlists, basic_spacing);
  1087.  
  1088.     xv_set(ip->controls5, XV_WIDTH, rig(ip->playlist) + 2, NULL);
  1089.  
  1090.     ip->delete = xv_create(ip->controls5, PANEL_BUTTON,
  1091.         XV_HELP_DATA, "workman:delete",
  1092.         PANEL_LABEL_STRING, "Delete track",
  1093.         PANEL_INACTIVE, TRUE,
  1094.         PANEL_NOTIFY_PROC, delete_from_playlist,
  1095.         NULL);
  1096.     put_down(ip->delete, ip->playlist, basic_spacing);
  1097.     center_x(ip->delete, ip->controls5);
  1098.  
  1099.     xv_set(ip->controls5, XV_HEIGHT, bot(ip->delete) + 5, NULL);
  1100.     window_fit(ip->plpopup);
  1101.  
  1102.     PANEL_EACH_ITEM(ip->controls5, item)
  1103.         xv_set(item, XV_KEY_DATA, INSTANCE, ip, NULL);
  1104.     PANEL_END_EACH;
  1105.  
  1106.     return (ip);
  1107. }
  1108.